﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using FikriKibar.Business.Abstract;
using FikriKibar.Common.Entities;
using FikriKibar.Common.Exceptions;
using FikriKibar.Common.Helpers;
using FikriKibar.Common.Validation.FluentValidation.ContentCategory;
using FikriKibar.DataAccess;
using FikriKibar.DataAccess.Abstract;
using FikriKibar.Entities.Abstract;
using FikriKibar.Entities.Composite.BaseModels;
using FikriKibar.Entities.Composite.ContentCategoryModels;
using FikriKibar.Entities.Concrete;
using FikriKibar.Globalization;



namespace FikriKibar.Business.Concrete
{
    public class ContentCategoryManager : IContentCategoryService
    {
        #region Global Declarations
        private readonly IContentCategoryDal _contentCategoryDal = new EfContentCategoryDal();

        private readonly IContentCategoryLanguageLineDal _contentCategoryLanguageLineDal = new EfContentCategoryLanguageLineDal();

        private readonly IContentCategoryLanguageLineHistoryDal _contentCategoryLanguageLineHistoryDal = new EfContentCategoryLanguageLineHistoryDal();

        private readonly IContentCategoryHistoryDal _contentCategoryHistoryDal = new EfContentCategoryHistoryDal();

        private readonly IContentTypeLanguageLineDal _contentTypeLanguageLineDal = new EfContentTypeLanguageLineDal();

        private readonly ILanguageDal _languageDal = new EfLanguageDal();

        private readonly ISettingDal _settingDal = new EfSettingDal();

        #endregion

        #region Methods

        public AddModel Add()
        {


            var contentCategoryList = _contentCategoryLanguageLineDal.Filter(e => e.Language.LanguageCode == Thread.CurrentThread.CurrentCulture.Name);
            foreach (var item in contentCategoryList)
            {
                item.ParentNames = GetParentPath(item.ContentCategory, Thread.CurrentThread.CurrentCulture.Name);
            }

            return new AddModel
            {
                LanguageList = _languageDal.Filter(e => e.IsApproved),
                ContentTypeList = _contentTypeLanguageLineDal.Filter(e => e.Language.LanguageCode == Thread.CurrentThread.CurrentCulture.Name),
                ContentCategoryList = contentCategoryList
            };
        }
        public void Add(AddModel model)
        {
            var validator = new AddValidator(model);
            var contentCategoryLanguageLine = model.Item;
            model.LanguageList = _languageDal.Filter(e => e.IsApproved);
            model.ContentTypeList = _contentTypeLanguageLineDal.Filter(e => e.Language.LanguageCode == Thread.CurrentThread.CurrentCulture.Name);
            model.ContentCategoryList = _contentCategoryLanguageLineDal.Filter(e => e.Language.LanguageCode == Thread.CurrentThread.CurrentCulture.Name);
            var validationResults = validator.Validate();
            if (!validator.IsValid)
            {
                throw new ValidationException(Resources.InvalidEntityMessage)
                {
                    ValidationResult = validationResults
                };
            }
            var fikriKibarIdentity = (FikriKibarIdentity)Thread.CurrentPrincipal.Identity;


            var contentCategory = new ContentCategory
            {
                ContentTypeId = model.SelectedContentTypeId,
                ParentId = model.SelectedContentCategoryId,
                CreateDate = DateTime.Now,
                CreatedBy = fikriKibarIdentity.UserId,
                UpdatedBy = fikriKibarIdentity.UserId,
                UpdateDate = DateTime.Now

            };

            var addedContentCategory = _contentCategoryDal.Add(contentCategory);
            foreach (var languageId in model.SelectedLanguageIds)
            {
                contentCategoryLanguageLine.ContentCategoryId = addedContentCategory.Id;
                contentCategoryLanguageLine.ContentCategory = null;
                contentCategoryLanguageLine.LanguageId = languageId;
                contentCategoryLanguageLine.ContentCategoryName = model.Item.ContentCategoryName;
                contentCategoryLanguageLine.ContentCategoryDescription = model.Item.ContentCategoryDescription;
                contentCategoryLanguageLine.CreatedBy = fikriKibarIdentity.UserId;
                contentCategoryLanguageLine.CreateDate = DateTime.Now;
                contentCategoryLanguageLine.UpdatedBy = fikriKibarIdentity.UserId;
                contentCategoryLanguageLine.UpdateDate = DateTime.Now;
                contentCategoryLanguageLine.PublishBeginDate = model.Item.PublishBeginDate;
                contentCategoryLanguageLine.PublishEndDate = model.Item.PublishEndDate;
                contentCategoryLanguageLine.DisplayOrder = addedContentCategory.Id;
                contentCategoryLanguageLine.IsApproved = model.Item.IsApproved;
                _contentCategoryLanguageLineDal.Add(contentCategoryLanguageLine);
            }
        }
        public UpdateModel Update(int id, string language)
        {
            var contentCategoryLanguageLine = _contentCategoryLanguageLineDal.Filter(e => e.ContentCategoryId == id && e.Language.LanguageCode == language).FirstOrDefault();
            if (contentCategoryLanguageLine == null) throw new NotFoundException();
            return new UpdateModel
            {
                LanguageList = _languageDal.Filter(e => e.IsApproved),
                ContentTypeList = _contentTypeLanguageLineDal.Filter(e => e.Language.LanguageCode == Thread.CurrentThread.CurrentCulture.Name),
                SelectedLanguageCode = language,
                Item = contentCategoryLanguageLine,
                ItemId = contentCategoryLanguageLine.ContentCategoryId,
                SelectedContentTypeId = contentCategoryLanguageLine.ContentCategory.ContentTypeId
            };
        }
        public void Update(UpdateModel model)
        {
            var validator = new UpdateValidator(model);
            var validationResults = validator.Validate();
            if (!validator.IsValid)
            {
                throw new ValidationException(Resources.InvalidEntityMessage)
                {
                    ValidationResult = validationResults
                };
            }
            var fikriKibarIdentity = (FikriKibarIdentity)Thread.CurrentPrincipal.Identity;

            var contentCategory = _contentCategoryDal.GetById(model.ItemId);

            var contentCategoryHistory = new ContentCategoryHistory
            {
                ContentCategoryId = contentCategory.Id,
                ContentTypeId = contentCategory.ContentTypeId,
                CreateDate = contentCategory.CreateDate,
                CreatedBy = contentCategory.CreatedBy,
                UpdateDate = contentCategory.UpdateDate,
                UpdatedBy = contentCategory.UpdatedBy,
                IsDeleted = false
            };
            _contentCategoryHistoryDal.Add(contentCategoryHistory);
            contentCategory.UpdateDate = DateTime.Now;
            contentCategory.UpdatedBy = fikriKibarIdentity.UserId;
            contentCategory.ContentTypeId = model.SelectedContentTypeId;
            var affectedContentCategory = _contentCategoryDal.Update(contentCategory);

            var contentCategoryLanguageLine = _contentCategoryLanguageLineDal.Filter(e => e.ContentCategoryId == model.ItemId && e.Language.LanguageCode == model.SelectedLanguageCode).FirstOrDefault();

            if (contentCategoryLanguageLine == null)
            {
                contentCategoryLanguageLine = new ContentCategoryLanguageLine
                {
                    ContentCategoryId = affectedContentCategory.Id,
                    ContentCategory = null,
                    LanguageId = _languageDal.GetByCode(model.SelectedLanguageCode).Id,
                    ContentCategoryName = model.Item.ContentCategoryName,
                    ContentCategoryDescription = model.Item.ContentCategoryDescription,
                    CreatedBy = fikriKibarIdentity.UserId,
                    CreateDate = DateTime.Now,
                    UpdatedBy = fikriKibarIdentity.UserId,
                    UpdateDate = DateTime.Now,
                    PublishBeginDate = model.Item.PublishBeginDate,
                    PublishEndDate = model.Item.PublishEndDate,
                    DisplayOrder = affectedContentCategory.Id,
                    IsApproved = model.Item.IsApproved
                };
                _contentCategoryLanguageLineDal.Add(contentCategoryLanguageLine);

            }
            else
            {
                var contentCategoryLanguageLineHistory = new ContentCategoryLanguageLineHistory
                {
                    ContentCategoryLanguageLineId = contentCategoryLanguageLine.Id,
                    ContentCategoryId = contentCategoryLanguageLine.ContentCategoryId,
                    LanguageId = contentCategoryLanguageLine.LanguageId,
                    ContentCategoryName = contentCategoryLanguageLine.ContentCategoryName,
                    ContentCategoryDescription = contentCategoryLanguageLine.ContentCategoryDescription,
                    CreateDate = contentCategoryLanguageLine.CreateDate,
                    CreatedBy = contentCategory.CreatedBy,
                    UpdateDate = contentCategory.UpdateDate,
                    UpdatedBy = contentCategory.UpdatedBy,
                    PublishBeginDate = contentCategoryLanguageLine.PublishBeginDate,
                    PublishEndDate = contentCategoryLanguageLine.PublishEndDate,
                    DisplayOrder = contentCategoryLanguageLine.DisplayOrder,
                    IsApproved = contentCategoryLanguageLine.IsApproved,
                    IsDeleted = false
                };
                _contentCategoryLanguageLineHistoryDal.Add(contentCategoryLanguageLineHistory);

                contentCategoryLanguageLine.UpdateDate = DateTime.Now;
                contentCategoryLanguageLine.UpdatedBy = fikriKibarIdentity.UserId;
                contentCategoryLanguageLine.ContentCategoryName = model.Item.ContentCategoryName;
                contentCategoryLanguageLine.ContentCategoryDescription = model.Item.ContentCategoryDescription;
                contentCategoryLanguageLine.PublishBeginDate = model.Item.PublishBeginDate;
                contentCategoryLanguageLine.PublishEndDate = model.Item.PublishEndDate;
                contentCategoryLanguageLine.IsApproved = model.Item.IsApproved;

                _contentCategoryLanguageLineDal.Update(contentCategoryLanguageLine);
            }




        }
        public ListModel<ContentCategoryLanguageLine> GetList(string searchTerm, string languageCode, int status, int index, int size, string idsForSort, string idsForApprove, string idsForDelete)
        {
            var model = new ListModel<ContentCategoryLanguageLine>
            {
                Paging = new Paging(),
                ItemList = new List<ContentCategoryLanguageLine>(),
                LanguageList = _languageDal.Filter(e => e.IsApproved)
            };

            if (idsForDelete != null)
            {
                var ids = idsForDelete;
                ids = ids.Remove(ids.Length - 1);
                var idArray = ids.Split(',');
                var idList = idArray.Select(id => id.ConvertToInt()).ToList();
                DeleteSelected(idList, languageCode);

            }
            model.IdsForDelete = null;


            if (idsForApprove != null)
            {
                var ids = idsForApprove;
                ids = ids.Remove(ids.Length - 1);
                var idArray = ids.Split(',');
                var idList = idArray.Select(id => id.ConvertToInt()).ToList();
                ApproveSelected(idList, languageCode);
            }

            model.IdsForApprove = null;

            var sortHelper = new SortHelper<ContentCategoryLanguageLine>();
            sortHelper.OrderByDescending(t => t.DisplayOrder);

            model.Paging.CurrentPageSize = size;
            model.Paging.CurrentPage = index;
            model.SelectedStatus = status;

            if (status != -1)
            {
                var blStatus = status.ToString().ConvertToBoolean();
                model.Paging.TotalItemCount = _contentCategoryLanguageLineDal.GetTotalCount(e => e.ContentCategoryName.Contains(searchTerm) && e.Language.LanguageCode == languageCode && e.IsApproved == blStatus);
            }
            else
            {
                model.Paging.TotalItemCount = _contentCategoryLanguageLineDal.GetTotalCount(e => e.ContentCategoryName.Contains(searchTerm) && e.Language.LanguageCode == languageCode);
            }

            var pageSizeListSetting = _settingDal.GetValueByKey("PageSizeList");
            var pageSizeSettingValue = "10,25,50,100";
            if (pageSizeListSetting != null)
            {
                pageSizeSettingValue = pageSizeListSetting;
            }
            var pageSizeList = pageSizeSettingValue.Split(',').Select(t => new KeyValuePair<int, string>(t.ConvertToInt(), t)).ToList();

            pageSizeList.Insert(0, new KeyValuePair<int, string>(-1, "[" + Resources.All + "]"));
            model.Paging.PageSizeList = pageSizeList;


            if (status != -1)
            {
                var blStatus = status.ToString().ConvertToBoolean();
                model.ItemList = model.Paging.CurrentPageSize > 0 ? _contentCategoryLanguageLineDal.Filter(e => e.ContentCategoryName.Contains(searchTerm) && e.Language.LanguageCode == languageCode && e.IsApproved == blStatus, sortHelper, index, size) : _contentCategoryLanguageLineDal.Filter(e => e.ContentCategoryName.Contains(searchTerm) && e.Language.LanguageCode == languageCode && e.IsApproved == blStatus);
            }
            else
            {
                model.ItemList = model.Paging.CurrentPageSize > 0 ? _contentCategoryLanguageLineDal.Filter(e => e.ContentCategoryName.Contains(searchTerm) && e.Language.LanguageCode == languageCode, sortHelper, index, size) : _contentCategoryLanguageLineDal.Filter(e => e.ContentCategoryName.Contains(searchTerm) && e.Language.LanguageCode == languageCode);
            }


            if (idsForSort != null)
            {
                var ids = idsForSort;
                ids = ids.Remove(ids.Length - 1);
                var idArray = ids.Split(',');
                var idList = idArray.Select(id => id.ConvertToInt()).ToList();
                model.ItemList = SaveSort(idList, languageCode);
            }
            model.IdsForSort = null;

            model.Searched = searchTerm;
            model.SelectedLanguageCode = languageCode;

            model.Paging.CurrentPage = index;
            model.Paging.TotalPageCount = (int)Math.Ceiling((float)model.Paging.TotalItemCount / size);

            foreach (var contentCategoryLanguageLine in model.ItemList)
            {
                contentCategoryLanguageLine.ParentNames = GetParentPath(contentCategoryLanguageLine.ContentCategory, languageCode);
            }


            return model;
        }

        public void Delete(int id, string language)
        {
            var contentCategoryLanguageLine = _contentCategoryLanguageLineDal.Filter(e => e.Language.LanguageCode == language).FirstOrDefault(e => e.ContentCategory.Id == id);
            if (contentCategoryLanguageLine == null) return;
            var fikriKibarIdentity = (FikriKibarIdentity)Thread.CurrentPrincipal.Identity;
            var contentCategoryLanguageLineHistory = new ContentCategoryLanguageLineHistory
            {
                ContentCategoryLanguageLineId = contentCategoryLanguageLine.Id,
                ContentCategoryId = contentCategoryLanguageLine.ContentCategoryId,
                LanguageId = contentCategoryLanguageLine.LanguageId,
                ContentCategoryName = contentCategoryLanguageLine.ContentCategoryName,
                ContentCategoryDescription = contentCategoryLanguageLine.ContentCategoryDescription,
                CreateDate = contentCategoryLanguageLine.CreateDate,
                CreatedBy = contentCategoryLanguageLine.CreatedBy,
                UpdateDate = DateTime.Now,
                UpdatedBy = fikriKibarIdentity.UserId,
                PublishBeginDate = contentCategoryLanguageLine.PublishBeginDate,
                PublishEndDate = contentCategoryLanguageLine.PublishEndDate,
                DisplayOrder = contentCategoryLanguageLine.DisplayOrder,
                IsApproved = contentCategoryLanguageLine.IsApproved,
                IsDeleted = true
            };
            _contentCategoryLanguageLineHistoryDal.Add(contentCategoryLanguageLineHistory);
            _contentCategoryLanguageLineDal.Delete(contentCategoryLanguageLine);

            if (_contentCategoryLanguageLineDal.Filter(e => e.ContentCategoryId == id).Any()) return;
            var contentCategory = _contentCategoryDal.GetById(id);
            if (contentCategory == null) return;
            var contentCategoryHistory = new ContentCategoryHistory
            {
                ContentCategoryId = contentCategory.Id,
                CreateDate = contentCategory.CreateDate,
                CreatedBy = contentCategory.CreatedBy,
                UpdateDate = DateTime.Now,
                UpdatedBy = fikriKibarIdentity.UserId,
                IsDeleted = true
            };
            _contentCategoryHistoryDal.Add(contentCategoryHistory);
            _contentCategoryDal.Delete(contentCategory);
        }

        private List<ContentCategoryLanguageLine> SaveSort(IReadOnlyList<int> idList, string languageCode)
        {
            var returnedValue = new List<ContentCategoryLanguageLine>();
            for (var i = 0; i < idList.Count; i++)
            {
                var contentCategoryLanguageLine = _contentCategoryLanguageLineDal.Filter(e => e.Language.LanguageCode == languageCode).FirstOrDefault(e => e.ContentCategory.Id == idList[i]);

                if (contentCategoryLanguageLine == null) continue;
                var contentCategory = _contentCategoryDal.GetById(contentCategoryLanguageLine.ContentCategory.Id);
                var fikriKibarIdentity = (FikriKibarIdentity)Thread.CurrentPrincipal.Identity;

                var contentCategoryHistory = new ContentCategoryHistory
                {
                    ContentCategoryId = contentCategory.Id,
                    CreateDate = contentCategory.CreateDate,
                    CreatedBy = contentCategory.CreatedBy,
                    UpdateDate = DateTime.Now,
                    UpdatedBy = fikriKibarIdentity.UserId,
                    IsDeleted = false
                };
                _contentCategoryHistoryDal.Add(contentCategoryHistory);


                contentCategory.UpdatedBy = fikriKibarIdentity.UserId;
                contentCategory.UpdateDate = DateTime.Now;
                _contentCategoryDal.Update(contentCategory);

                var contentCategoryLanguageLineHistory = new ContentCategoryLanguageLineHistory
                {
                    ContentCategoryLanguageLineId = contentCategoryLanguageLine.Id,
                    ContentCategoryId = contentCategoryLanguageLine.ContentCategoryId,
                    LanguageId = contentCategoryLanguageLine.LanguageId,
                    ContentCategoryName = contentCategoryLanguageLine.ContentCategoryName,
                    ContentCategoryDescription = contentCategoryLanguageLine.ContentCategoryDescription,
                    CreateDate = contentCategoryLanguageLine.CreateDate,
                    CreatedBy = contentCategoryLanguageLine.CreatedBy,
                    UpdateDate = DateTime.Now,
                    UpdatedBy = fikriKibarIdentity.UserId,
                    PublishBeginDate = contentCategoryLanguageLine.PublishBeginDate,
                    PublishEndDate = contentCategoryLanguageLine.PublishEndDate,
                    DisplayOrder = contentCategoryLanguageLine.DisplayOrder,
                    IsApproved = contentCategoryLanguageLine.IsApproved,
                    IsDeleted = false
                };
                _contentCategoryLanguageLineHistoryDal.Add(contentCategoryLanguageLineHistory);


                contentCategoryLanguageLine.DisplayOrder = i + 1;
                contentCategoryLanguageLine.UpdatedBy = fikriKibarIdentity.UserId;
                contentCategoryLanguageLine.UpdateDate = DateTime.Now;
                contentCategoryLanguageLine.ContentCategory = contentCategory;
                _contentCategoryLanguageLineDal.Update(contentCategoryLanguageLine);
                returnedValue.Add(contentCategoryLanguageLine);
            }
            return returnedValue;
        }
        private void ApproveSelected(IEnumerable<int> idList, string languageCode)
        {
            foreach (var id in idList)
            {
                var contentCategoryLanguageLine = _contentCategoryLanguageLineDal.Filter(e => e.Language.LanguageCode == languageCode).FirstOrDefault(e => e.ContentCategory.Id == id);
                if (contentCategoryLanguageLine == null) continue;
                var contentCategory = _contentCategoryDal.GetById(contentCategoryLanguageLine.ContentCategory.Id);
                var fikriKibarIdentity = (FikriKibarIdentity)Thread.CurrentPrincipal.Identity;
                var contentCategoryHistory = new ContentCategoryHistory
                {
                    ContentCategoryId = contentCategory.Id,
                    CreateDate = contentCategory.CreateDate,
                    CreatedBy = contentCategory.CreatedBy,
                    UpdateDate = DateTime.Now,
                    UpdatedBy = fikriKibarIdentity.UserId,
                    IsDeleted = false
                };
                _contentCategoryHistoryDal.Add(contentCategoryHistory);
                contentCategory.UpdatedBy = fikriKibarIdentity.UserId;
                contentCategory.UpdateDate = DateTime.Now;
                _contentCategoryDal.Update(contentCategory);

                var contentCategoryLanguageLineHistory = new ContentCategoryLanguageLineHistory
                {
                    ContentCategoryLanguageLineId = contentCategoryLanguageLine.Id,
                    ContentCategoryId = contentCategoryLanguageLine.ContentCategoryId,
                    LanguageId = contentCategoryLanguageLine.LanguageId,
                    ContentCategoryName = contentCategoryLanguageLine.ContentCategoryName,
                    ContentCategoryDescription = contentCategoryLanguageLine.ContentCategoryDescription,
                    CreateDate = contentCategoryLanguageLine.CreateDate,
                    CreatedBy = contentCategoryLanguageLine.CreatedBy,
                    UpdateDate = DateTime.Now,
                    UpdatedBy = fikriKibarIdentity.UserId,
                    PublishBeginDate = contentCategoryLanguageLine.PublishBeginDate,
                    PublishEndDate = contentCategoryLanguageLine.PublishEndDate,
                    DisplayOrder = contentCategoryLanguageLine.DisplayOrder,
                    IsApproved = contentCategoryLanguageLine.IsApproved,
                    IsDeleted = false
                };
                _contentCategoryLanguageLineHistoryDal.Add(contentCategoryLanguageLineHistory);


                contentCategoryLanguageLine.UpdatedBy = fikriKibarIdentity.UserId;
                contentCategoryLanguageLine.UpdateDate = DateTime.Now;
                contentCategoryLanguageLine.IsApproved = true;
                contentCategoryLanguageLine.ContentCategory = contentCategory;
                _contentCategoryLanguageLineDal.Update(contentCategoryLanguageLine);

            }
        }
        private void DeleteSelected(IEnumerable<int> idList, string languageCode)
        {
            foreach (var id in idList)
            {
                Delete(id, languageCode);
            }
        }
        private string GetParentPath(ContentCategory contentCategory, string language)
        {
            var list = _contentCategoryDal.GetParentList(contentCategory, new List<ContentCategory>());
            list.Reverse();
            var str = string.Empty;
            foreach (var item in list)
            {
                var lst = _contentCategoryLanguageLineDal.Filter(e => e.ContentCategoryId == item.Id && e.Language.LanguageCode == language);
                var contentCategoryLanguageLine = lst?.FirstOrDefault();
                if (contentCategoryLanguageLine != null)
                {
                    str += " » " + contentCategoryLanguageLine.ContentCategoryName;
                }
            }
            return str;
        }

        #endregion
    }
}
